package evaluation;
import java.util.ArrayList;
import java.util.List;
import weka.core.Instance;
import mulan.classifier.MultiLabelLearner;
import mulan.classifier.MultiLabelOutput;
import mulan.data.MultiLabelInstances;


public class MulanEvaluator implements PerformanceEvaluator,Runnable {
	
	String test_file,xml_file,out_file;
	MultiLabelInstances train,test;
	MultiLabelLearner learner;
	PerformanceEvaluation pe;
	List<String> labels;
			
	public MulanEvaluator(String test_file, String xml_file,
			MultiLabelLearner learner)  {
		this.test_file = test_file;
		this.xml_file = xml_file;
		this.learner = learner;
	}
	
	public void setOutFile(String out_file) {
		this.out_file = out_file;
	}

	public PerformanceEvaluation getPerformanceEvaluation() {
		return pe;
	}

	@Override
	public PerformanceEvaluation evaluate() {
		try {
			pe = new PerformanceEvaluation();
			double start = System.nanoTime();
			buildModel();
			test = new MultiLabelInstances(test_file, xml_file);
			labels = new ArrayList<String>();
			int indices[] = test.getLabelIndices();
			for ( int k = 0 ; k < indices.length ; ++k ) {
				labels.add(test.getDataSet().attribute(indices[k]).name());
			}
			pe.setLabels(labels);
			pe.setMeasures(pe.prepareMeasures(labels.size()));
			double start_building = System.nanoTime();
			double finished_building = System.nanoTime();
			double total_predicting_time = 0;
			for ( int k = 0 ; k < Math.min(test.getDataSet().numInstances(),100) ; ++k ) {
				Instance i = test.getDataSet().instance(k);
				double start_predicting = System.nanoTime();
				MultiLabelOutput mlo = learner.makePrediction(i);
				double finished_predicting = System.nanoTime();
				total_predicting_time += finished_predicting-start_predicting;
				pe.update(mlo,getTruelabels(i,test));	
				System.out.println(k);
			}
			double end = System.nanoTime();
			pe.setBuild_time_ns(finished_building-start_building);
			pe.setClassify_time_ns(total_predicting_time);
			pe.setRun_time_ns(end-start);
			pe.setClassifier(learner.toString());
			pe.setTest_file(test_file);
			pe.setNum_test_instances(test.getNumInstances());
			learner = null;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return pe;
	}

	void buildModel() {}

	private boolean[] getTruelabels(Instance i,MultiLabelInstances set) {
		int label_indices[] = set.getLabelIndices();
		boolean[] res = new boolean[set.getNumLabels()];
		for ( int k = 0 ; k < label_indices.length ; ++k ) {
			res[k] = i.value(label_indices[k])>0.1;
		}
		return res;
	}

	@Override
	public void run() {
		evaluate();
		pe.flushToFile(out_file);
	}

}
